package page

import (
	"context"

	"BookStack/pkg/errors"
)

// Service 页面领域服务接口
type Service interface {
	// Create 创建页面
	Create(ctx context.Context, title, slug, content, description string, status int, userID uint) (*Page, error)

	// Update 更新页面
	Update(ctx context.Context, id uint, title, slug, content, description string, status int) (*Page, error)

	// GetByID 通过ID获取页面
	GetByID(ctx context.Context, id uint) (*Page, error)

	// GetBySlug 通过Slug获取页面
	GetBySlug(ctx context.Context, slug string) (*Page, error)

	// Delete 删除页面
	Delete(ctx context.Context, id uint) error

	// SetStatus 设置页面状态
	SetStatus(ctx context.Context, id uint, status int) (*Page, error)

	// IncrementViewCount 增加页面浏览次数
	IncrementViewCount(ctx context.Context, id uint) error

	// List 获取页面列表
	List(ctx context.Context, offset, limit int, status *int) ([]*Page, int64, error)
}

// 页面领域服务实现
type service struct {
	repo Repository
}

// NewPageService 创建页面领域服务
func NewPageService(repo Repository) Service {
	return &service{
		repo: repo,
	}
}

// Create 创建页面
func (s *service) Create(ctx context.Context, title, slug, content, description string, status int, userID uint) (*Page, error) {
	// 检查标题是否已存在
	exists, err := s.repo.ExistsByTitle(ctx, title, 0)
	if err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	if exists {
		return nil, errors.New(errors.ErrCodePageTitleExists, "").WithDetails(map[string]interface{}{
			"title": title,
		})
	}

	// 检查Slug是否已存在
	exists, err = s.repo.ExistsBySlug(ctx, slug, 0)
	if err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	if exists {
		return nil, errors.New(errors.ErrCodePageSlugExists, "").WithDetails(map[string]interface{}{
			"slug": slug,
		})
	}

	// 创建页面
	page := NewPage(title, slug, content, description, status, userID)
	if err := s.repo.Create(ctx, page); err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}

	return page, nil
}

// Update 更新页面
func (s *service) Update(ctx context.Context, id uint, title, slug, content, description string, status int) (*Page, error) {
	// 获取现有页面
	page, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	if page == nil {
		return nil, errors.New(errors.ErrCodePageNotFound, "").WithDetails(map[string]interface{}{
			"page_id": id,
		})
	}

	// 检查标题是否已存在（排除当前页面）
	if page.Title != title {
		exists, err := s.repo.ExistsByTitle(ctx, title, id)
		if err != nil {
			return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
		}
		if exists {
			return nil, errors.New(errors.ErrCodePageTitleExists, "").WithDetails(map[string]interface{}{
				"title": title,
			})
		}
	}

	// 检查Slug是否已存在（排除当前页面）
	if page.Slug != slug {
		exists, err := s.repo.ExistsBySlug(ctx, slug, id)
		if err != nil {
			return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
		}
		if exists {
			return nil, errors.New(errors.ErrCodePageSlugExists, "").WithDetails(map[string]interface{}{
				"slug": slug,
			})
		}
	}

	// 更新页面
	page.UpdateContent(title, slug, content, description)

	// 如果状态有变化则更新状态
	if page.Status != status {
		page.UpdateStatus(status)
	}

	if err := s.repo.Update(ctx, page); err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}

	return page, nil
}

// GetByID 通过ID获取页面
func (s *service) GetByID(ctx context.Context, id uint) (*Page, error) {
	page, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	if page == nil {
		return nil, errors.New(errors.ErrCodePageNotFound, "").WithDetails(map[string]interface{}{
			"page_id": id,
		})
	}
	return page, nil
}

// GetBySlug 通过Slug获取页面
func (s *service) GetBySlug(ctx context.Context, slug string) (*Page, error) {
	page, err := s.repo.GetBySlug(ctx, slug)
	if err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	if page == nil {
		return nil, errors.New(errors.ErrCodePageNotFound, "").WithDetails(map[string]interface{}{
			"page_slug": slug,
		})
	}
	return page, nil
}

// Delete 删除页面
func (s *service) Delete(ctx context.Context, id uint) error {
	// 检查页面是否存在
	page, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	if page == nil {
		return errors.New(errors.ErrCodePageNotFound, "").WithDetails(map[string]interface{}{
			"page_id": id,
		})
	}

	// 删除页面
	if err := s.repo.Delete(ctx, id); err != nil {
		return errors.Wrap(err, errors.ErrCodeDatabase, "")
	}

	return nil
}

// SetStatus 设置页面状态
func (s *service) SetStatus(ctx context.Context, id uint, status int) (*Page, error) {
	// 检查页面是否存在
	page, err := s.repo.GetByID(ctx, id)
	if err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	if page == nil {
		return nil, errors.New(errors.ErrCodePageNotFound, "").WithDetails(map[string]interface{}{
			"page_id": id,
		})
	}

	// 更新状态
	if err := s.repo.UpdateStatus(ctx, id, status); err != nil {
		return nil, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}

	// 更新内存中的状态
	page.Status = status
	return page, nil
}

// IncrementViewCount 增加页面浏览次数
func (s *service) IncrementViewCount(ctx context.Context, id uint) error {
	err := s.repo.IncrementViewCount(ctx, id)
	if err != nil {
		return errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	return nil
}

// List 获取页面列表
func (s *service) List(ctx context.Context, offset, limit int, status *int) ([]*Page, int64, error) {
	pages, total, err := s.repo.List(ctx, offset, limit, status)
	if err != nil {
		return nil, 0, errors.Wrap(err, errors.ErrCodeDatabase, "")
	}
	return pages, total, nil
}
